package com.yesep.learn.comm.middle.util;

import cn.hutool.core.io.resource.ResourceUtil;
import org.python.core.PyClass;
import org.python.core.PyFunction;
import org.python.core.PyInstance;
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;

import java.util.Properties;

public class JythonFactory {
    private static JythonFactory instance;
    private PythonInterpreter interpreter = null;

    /**
     * @Description: 初始化jython
     */
    private JythonFactory() {
        //初始化site 配置
        Properties props = new Properties();
        props.put("python.home", ""); //python Lib 或 jython Lib,根据系统中该文件目录路径
        props.put("python.console.encoding", "UTF-8");
        props.put("python.security.respectJavaAccessibility", "false");
        props.put("python.import.site", "false");
        Properties preprops = System.getProperties();
        PythonInterpreter.initialize(preprops, props, new String[0]);
        //创建PythonInterpreter 对象
        interpreter = new PythonInterpreter();
    }

    public static JythonFactory getInstance() {
        if (null == instance) {
            instance = new JythonFactory();
        }
        return instance;
    }

    /**
     * 加载python 源码文件
     */
    public void execfile(String pyfile) {
        interpreter.execfile(ResourceUtil.getResource(pyfile).getPath());
    }

    public PyObject getPyObject(String name) {
        PyObject obj = (PyObject) interpreter.get(name, PyObject.class);
        return obj;
    }

    public PyObject getPyObject(String pyfile, String name) {
        this.execfile(pyfile);
        return getPyObject(name);
    }

    public PyClass getPyClass(String className) {
        PyClass cls = (PyClass) interpreter.get(className, PyClass.class);
        return cls;
    }

    public PyClass getPyClass(String pyfile, String className) {
        this.execfile(pyfile);
        return getPyClass(className);
    }

    public PyInstance getPyInstance(String className, PyObject dict) {
        PyClass cls = getPyClass(className);
        PyInstance inst = new PyInstance(cls, dict);
        return inst;
    }

    public PyInstance getPyInstance(String pyfile, String className, PyObject dict) {
        this.execfile(pyfile);
        return getPyInstance(className, dict);
    }

    /**
     * 加载python 源码文件中的某个方法
     */
    public PyFunction getPyFunction(String functionName) {
        PyFunction func = (PyFunction) interpreter.get(functionName, PyFunction.class);
        return func;
    }

    public PyFunction getPyFunction(String pyfile, String functionName) {
        this.execfile(pyfile);
        return getPyFunction(functionName);
    }


    public PyObject execute(String functionName, PyObject... args) {
        PyFunction func = getPyFunction(functionName);
        PyObject pyobj = ((args == null || args.length < 1) ? func.__call__() : func.__call__(args));
        return pyobj;
    }

    public PyObject execute(String pyfile, String functionName, PyObject... args) {
        this.execfile(pyfile);
        return execute(functionName, args);
    }

    public <T> T execute(String functionName, Class<T> cls, PyObject... args) {
        PyObject pyobj = execute(functionName, args);
        T javaObj = (T) pyobj.__tojava__(cls);
        return javaObj;
    }

    public <T> T execute(String pyfile, String functionName, Class<T> cls, PyObject... args) {
        this.execfile(pyfile);
        return execute(functionName, cls, args);
    }

    public PyObject invoke(String className, PyObject dict, String methodName, PyObject... args) {
        PyInstance inst = getPyInstance(className, dict);
        return inst.invoke(methodName, args);
    }

    public PyObject invoke(String pyfile, String className, PyObject dict, String methodName, PyObject... args) {
        this.execfile(pyfile);
        return invoke(className, dict, methodName, args);
    }

    public <T> T invoke(String className, PyObject dict, String methodName, Class<T> cls, PyObject... args) {
        PyObject pyobj = invoke(className, dict, methodName, args);
        T javaObj = (T) pyobj.__tojava__(cls);
        return javaObj;
    }

    public <T> T invoke(String pyfile, String className, PyObject dict, String methodName, Class<T> cls, PyObject... args) {
        this.execfile(pyfile);
        return invoke(className, dict, methodName, cls, args);
    }
}
